package cc.linker.steplink.crm.merchanth5.service.impl;

import cc.linker.steplink.crm.commons.FeeConstants;
import cc.linker.steplink.crm.commons.constant.TlPayConstant;
import cc.linker.steplink.crm.commons.constant.WcPayConstant;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.WcPayProperties;
import cc.linker.steplink.crm.commons.utils.CalendarUtils;
import cc.linker.steplink.crm.commons.utils.NumberUtils;
import cc.linker.steplink.crm.commons.utils.TransactionOrderUtil;
import cc.linker.steplink.crm.merchanth5.dao.acs.MerchantWalletDao;
import cc.linker.steplink.crm.merchanth5.dao.acs.PurchaseProcessDao;
import cc.linker.steplink.crm.merchanth5.dao.acs.WithdrawTaskDao;
import cc.linker.steplink.crm.merchanth5.pojo.WithdrawTaskPo;
import cc.linker.steplink.crm.merchanth5.service.MaiBaoLaService;
import cc.linker.steplink.crm.merchanth5.service.MallService;
import cc.linker.steplink.crm.merchanth5.service.acs.MerchantWalletService;
import cc.linker.steplink.crm.merchanth5.service.acs.PurchaseProcessService;
import cc.linker.steplink.crm.merchanth5.service.tl.LedgerProcessService;
import cc.linker.steplink.crm.response.GlobalException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
@Service
public class MerchantWalletServiceImpl implements MerchantWalletService {

    @Autowired
    private MerchantWalletDao merchantWalletDao;
    @Autowired
    private PurchaseProcessDao purchaseProcessDao;
    @Autowired
    private PurchaseProcessService PurchaseProcessService;
    @Autowired
    private WcPayProperties wcPayProperties;
    @Autowired
    private HttpService httpService;
    @Autowired
    private MallService mallService;
    @Autowired
    private MaiBaoLaService maiBaoLaService;
    @Autowired
    private WithdrawTaskDao withdrawTaskDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private LedgerProcessService ledgerProcessService;

    private static final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public Map<String, Object> walletInfo(String customerId) {
        Map<String, Object> res = merchantWalletDao.walletInfo(customerId);
        Long customerBalance = Long.valueOf(res.get("customerBalance").toString());
        Long customerFreeze = Long.valueOf(res.get("customerFreeze").toString());
        Map<String, Object> result = new HashMap<>();
        result.put("cutomerBalance", NumberUtils.fenToYuan(customerBalance));
        result.put("customerFreeze", NumberUtils.fenToYuan(customerFreeze));
        result.put("customerTotal", NumberUtils.fenToYuan(customerFreeze + customerBalance));

        return result;
    }

    @Override
    public Integer mobileCount(String phone, String customerId) {
        return merchantWalletDao.mobileCount(phone, customerId);
    }

    @Override
    public JSONObject addAccount(Map<String, String> params) throws Exception {
        // 判断是否已存在该记录
//        if(merchantWalletDao.ifExistAccount(params)){
//            throw GlobalException.build("您已申请开通！");
//        }
        Map<String, Object> map = new HashMap<>();
        map.put("accountType", "0");
        map.put("credentialNumber", params.get("customerCdno"));
        map.put("customerAddress", params.get("linkAddress"));
        map.put("customerEmail", params.get("linkEmail"));
        map.put("customerId", params.get("customerId"));
        map.put("customerName", params.get("customerName"));
        map.put("customerPhone", params.get("phone"));
        map.put("city", params.get("city"));
        map.put("province", params.get("province"));
        map.put("customerType", "11");
        map.put("institutionID", "005366");
        map.put("issDate", "");
        map.put("expiryDate", "");
        map.put("source", "1");
        map.put("clintType", maiBaoLaService.getAlias(params.get("orgId")));
        //  暂时注释请求中金
        JSONObject json = new JSONObject(map);
        String jsonString = json.toJSONString();
        String result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_OPEN_PAY_ACCOUNT, jsonString, WcPayConstant.JSON);
        JSONObject object = JSONObject.parseObject(result);
        return object;
    }

    @Override
    public Map<String, Object> getWithDraw(String customerId) throws Exception {
        Map<String, Object> res = new HashMap<>();
        //中金账户信息
        Map<String, Object> accountInfo = merchantWalletDao.getaccount(customerId);
        res.put("accountInfo", accountInfo);

        //银行卡信息
        Map<String, Object> bankInfo = merchantWalletDao.getBindBank(customerId);
        res.put("bankInfo", bankInfo);

        //账户余额
        Long balance = merchantWalletDao.getBalance(customerId);
        res.put("balance", NumberUtils.fenToYuan(balance));

        //提现手续费
        String orgId = merchantWalletDao.getOrgIdByCid(customerId);
        Map<String, Object> chargeInfo = merchantWalletDao.getChargeInfo(orgId);
        if (chargeInfo == null) {
            throw GlobalException.build("请联系平台开通提现功能！");
        }
        chargeInfo.put("withdrawCost", NumberUtils.fenToYuan(Long.valueOf(chargeInfo.get("withdrawCost").toString())));
        chargeInfo.put("withdrawLimit", NumberUtils.fenToYuan(Long.valueOf(chargeInfo.get("withdrawLimit").toString())));
        res.put("charge", chargeInfo);

        //是否存在提现状态的记录
        Boolean existWithDraw = merchantWalletDao.ifExistWithdraw(customerId, "11");
        res.put("existWithDraw", existWithDraw ? 1 : 0);
        return res;
    }

    @Override
    public JSONObject addBank(Map<String, String> params) throws Exception {
        //判断是否存在 如果已存在 判断是否存在提现中的记录
        if (merchantWalletDao.ifExistWithdraw(params.get("customerId"), "11")) {
            throw GlobalException.build("正在提现中，暂时无法更换银行卡。");
        }

        Map<String, Object> map = new HashMap<>();
        map.put("bankAccountName", params.get("bankAccountName"));
        map.put("bankAccountNumber", params.get("bankAccountNumber"));
        map.put("bankId", params.get("ubankId"));
        map.put("bankPhoneNumber", params.get("phone"));
        map.put("branchName", params.get("branchName"));
        map.put("clintType", maiBaoLaService.getAlias(params.get("orgId")));
        map.put("customerId", params.get("customerId"));
        map.put("cvn2", "");
        map.put("unionBank", "");
        map.put("validDate", "");
        //请求中金
        JSONObject json = new JSONObject(map);
        String jsonString = json.toJSONString();
        String result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_BANK_BIND_PAY, jsonString, WcPayConstant.JSON);
        JSONObject object = JSONObject.parseObject(result);
        return object;

//        Boolean res = true;
//
//        // bankStatus 状态:15=待短信验证；17=待被动打款验证；18=被动已打款待验证；20=处理中；30=成功；40=失败  bankcardinfo 表
//        // bkaccBindstatus 绑卡状态 0未绑定 1未激活 2已激活  account表
//        if(res){
//            //成功记录
//            params.put("bkaccBindstatus","1");
//            params.put("bankStatus","15");
//        }else{
//            params.put("bkaccBindstatus","0");
//            params.put("bankStatus","40");
//        }
//        merchantWalletDao.updateAccount(params);
//        merchantWalletDao.addBank(params);
//        return res;
    }

    @Override
    public JSONObject activeBank(Map<String, String> params) throws Exception {
        Map<String, Object> map = new HashMap<>();
        String clintType = maiBaoLaService.getAlias(params.get("orgId"));
        map.put("clintType", clintType);
        map.put("customerId", params.get("customerId"));
        map.put("verifyInfo", params.get("code"));
        map.put("verifyWay", "10");
        String string = JSON.toJSONString(map);
        // 请求中金
        String result = httpService.doPost(wcPayProperties.getAcsurl() + WcPayConstant.USER_BANK_ACTIVE_PAY, string, WcPayConstant.JSON);
        JSONObject object = JSONObject.parseObject(result);

        return object;

//        Boolean res = false;
//        if(object.containsKey("code") && "200".equals(object.get("code").toString())){
//            res = true;
//        }
//        return res;

//        Boolean res = true;
//        if(res){
//            //成功
//            params.put("bkaccBindstatus","2");
//            params.put("bankStatus","30");
//        }else{
//            //失败
//            params.put("bkaccBindstatus","1");
//            params.put("bankStatus","40");
//        }
//        merchantWalletDao.updateAccount(params);
//        merchantWalletDao.activeBank(params);
//        return res;
    }

    @Override
    public Map<String, Object> getGoldCoin(String customerId) {
        return merchantWalletDao.getGoldCoin(customerId);
    }

    @Override
    public Map<String, String> addWithDraw(Map<String, Object> params) {
        // 提现用户ID
        String customerId = params.get("customerId").toString();
        // 提现用户机构
        String orgId = params.get("orgId").toString();
        // 支付模式
        Integer payMode = mallService.getPayModeByOrgId(orgId);
        //银行卡数据
        Map<String, Object> bankInfo = merchantWalletDao.getBindBank(customerId);
        if (!bankInfo.containsKey("bankStatus") || !"30".equals(bankInfo.get("bankStatus").toString())) {
            throw GlobalException.build("您未绑定银行卡或者绑定的银行卡暂不可用！");
        }
        // 生成提现单号
        String withDrawId = "D".concat(String.valueOf(System.currentTimeMillis())).concat(customerId);

        // 提现金额
        BigDecimal bigDecimal = new BigDecimal(params.get("amount").toString()).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        BigDecimal multiply = bigDecimal.multiply(new BigDecimal(100));
        Long totalAmount = multiply.longValue();

        // 服务费计算 提现抽成
        Long serviceAmount = 0L;
        if (payMode == 2 || payMode == 3) {
            // 查询头寸金额
            //获取平台别名
            String clintType = payMode == 3 ? maiBaoLaService.getAliasByLinker() : maiBaoLaService.getAlias(orgId);
            Long reserveFundBalance = this.queryReserveFundBalance(clintType);
            if (totalAmount > reserveFundBalance) {
                throw GlobalException.build("暂时无法提现");
            }
            //region 获取需要分账的服务费有多少
            Map<String, Object> chargeInfo = merchantWalletDao.getChargeInfo(orgId);
            if ("1".equals(chargeInfo.get("withdrawTakeType").toString())) {
                //按比例抽成
                Double withdrawRate = Double.valueOf(chargeInfo.get("withdrawRate").toString());
                double v = totalAmount * withdrawRate / 100;
                serviceAmount = new BigDecimal(v).setScale(0, BigDecimal.ROUND_HALF_EVEN).longValue();
            } else if ("2".equals(chargeInfo.get("withdrawTakeType").toString())) {
                // 固定金额抽成
                serviceAmount = Long.valueOf(chargeInfo.get("withdrawCost").toString());
            }
            //endregion 服务费完毕
        }
        // 实际到账金额
        Long receiveAmount = totalAmount - serviceAmount;
        //获取该用户的可提现余额
        Map<String, Object> balanceMap = merchantWalletDao.getTotalBalance(customerId);
        //可用余额
        Long usableBalance = Long.parseLong(balanceMap.get("usableBalance").toString());
        //待结算余额
        Long freezeBalance = Long.parseLong(balanceMap.get("freezeBalance").toString());

        //如果可提现余额 - 提现总金额 小于0代表超额提现，
        if ((usableBalance - totalAmount) < 0) {
            throw GlobalException.build("账户可提现余额不足！");
        }

        //订单号
        String orderSn = TransactionOrderUtil.TYPE_SHOP + TransactionOrderUtil.getPrimaryKey();

        //手续费入账账户角色
        Integer serviceRole = 0;
        String unFreezeTime = "";

        //region 组装提现账单map
        Map<String, Object> insertWithdrawBillMap = new HashMap<>();

        //提现记账map
        Map<String, Object> addWithdrawBillMap = new HashMap<>();
        addWithdrawBillMap.put("payUser", customerId);
        addWithdrawBillMap.put("amount", receiveAmount);
        addWithdrawBillMap.put("payAccountBalance", usableBalance - totalAmount + freezeBalance);
        addWithdrawBillMap.put("type", "0");
        addWithdrawBillMap.put("orgId", orgId);
        addWithdrawBillMap.put("orderSn", orderSn);
        addWithdrawBillMap.put("busiSn", withDrawId);
        addWithdrawBillMap.put("payRole", 5);
        addWithdrawBillMap.put("payType", payMode);
        insertWithdrawBillMap.put("addWithdrawBillMap", addWithdrawBillMap);

        //用户提现记录
        Map<String, Object> customerWithDrawMap = new HashMap<>();
        customerWithDrawMap.put("customerId", customerId);
        customerWithDrawMap.put("withDrawId", withDrawId);
        customerWithDrawMap.put("status", "0");
        customerWithDrawMap.put("bankId", bankInfo.get("bankId").toString());
        customerWithDrawMap.put("branchName", StringUtils.isEmpty(bankInfo.get("branchName")) ? "" : bankInfo.get("branchName").toString());
        customerWithDrawMap.put("bankAccountNumber", bankInfo.get("bankAccountNumber").toString());
        customerWithDrawMap.put("totalAmount", totalAmount);
        customerWithDrawMap.put("serviceAmount", serviceAmount);
        customerWithDrawMap.put("receiveAmount", receiveAmount);
        customerWithDrawMap.put("orgId", orgId);
        customerWithDrawMap.put("customerType", "11");
        customerWithDrawMap.put("serialNumber", "");
        insertWithdrawBillMap.put("customerWithDrawMap", customerWithDrawMap);

        //手续费记账map
        Map<String, Object> addServiceBillMap = new HashMap<>();
        addServiceBillMap.putAll(addWithdrawBillMap);
        addServiceBillMap.put("receiveRole", 0);
        //endregion
//        payMode = 1;
        //paymode 2、3通联支付模式（3是联汇支付模式）
        if (payMode == 2 || payMode == 3) {
            //region 手续费入账账户和冻结时间
            String cid = PurchaseProcessService.getCustomerIdByFeeTypeAndOrdId(FeeConstants.HANDLING_FEE, orgId, payMode);
            if (!cid.startsWith("L")) {
                serviceRole = 1;
                // 计算冻结时间
                Integer freezeTime = purchaseProcessDao.getFreezeTimeByOrgId(orgId);
                freezeTime = freezeTime == null || freezeTime < 0 ? 30 : freezeTime;
                unFreezeTime = df.format(LocalDateTime.now().plusDays(freezeTime));
                addServiceBillMap.put("receiveRole", 1);
                addServiceBillMap.put("unfreezeTime", unFreezeTime);
            }
            //endregion
            String alias = payMode == 3 ? maiBaoLaService.getAliasByLinker() : maiBaoLaService.getAlias(orgId); //平台别名
            String serviceAccountType = PurchaseProcessService.getAccountTypeByFeeTypeAndOrgId(FeeConstants.HANDLING_FEE, orgId);
            String serviceAccount = purchaseProcessDao.getAccountUidByOrgId(orgId);

            //收款账户类型
            addServiceBillMap.put("receiveType", serviceAccountType);
            addServiceBillMap.put("serviceAccount", serviceAccount);
            addServiceBillMap.put("receiveUser", orgId);
            addServiceBillMap.put("amount", serviceAmount);
            addServiceBillMap.put("type", "11");
            insertWithdrawBillMap.put("addServiceBillMap", addServiceBillMap);

            //region 组装提现对象数据
            String industryCode = purchaseProcessDao.getOrgMerchantInfoByOrgId(orgId);
            String industryName = purchaseProcessDao.getIndustryNameByCode(industryCode); //行业名称
            WithdrawTaskPo withdrawTaskPo = new WithdrawTaskPo();
            withdrawTaskPo.withdrawId = UUID.randomUUID().toString();
            withdrawTaskPo.customerId = customerId;
            withdrawTaskPo.withdrawCode = withDrawId; //提现记录ID对应提现表
            withdrawTaskPo.withdrawMoney = totalAmount;
            withdrawTaskPo.serviceMoney = serviceAmount;
            withdrawTaskPo.receiveMoney = receiveAmount;
            withdrawTaskPo.amount = receiveAmount;
            withdrawTaskPo.appId = purchaseProcessDao.getAppIdByOrgId((payMode == 3 ? "linker" : orgId));
            withdrawTaskPo.industryCode = !StringUtils.isEmpty(industryCode) ? industryCode : "";
            withdrawTaskPo.industryName = !StringUtils.isEmpty(industryName) ? industryName : "";
            withdrawTaskPo.source = 1;
            withdrawTaskPo.clientType = alias;
            withdrawTaskPo.validateType = 0;
            withdrawTaskPo.fee = 0L;
            withdrawTaskPo.feeCustomerId = orgId;
            withdrawTaskPo.orderSn = orderSn;
            withdrawTaskPo.remark = "";
            withdrawTaskPo.orgId = orgId;
            withdrawTaskPo.status = 0;
            withdrawTaskPo.billMapJson = JSON.toJSONString(insertWithdrawBillMap);
            withdrawTaskPo.isServiceTransfer = 0;
            withdrawTaskPo.isUserTransfer = 0;
            //给用户的orderSn
            withdrawTaskPo.customerOrderSn = TransactionOrderUtil.TYPE_SHOP + TransactionOrderUtil.getPrimaryKey();
            //给大麦的服务费的orderSn
            withdrawTaskPo.serviceOrderSn = serviceAmount > 0 ? TransactionOrderUtil.TYPE_SHOP + TransactionOrderUtil.getPrimaryKey() : "";
            //endregion

            //region 判断当前时间是否在银行可提现时间内，如果是那么提现，如果不是记录数据库任务，在允许时间进行提现
            Date now = new Date();
            SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
            String nowDate = format.format(now);
            //如果是在可提现范围之内
            String startDate = params.containsKey("startDate") ? params.get("startDate").toString() : "07:15:00";
            String endDate = params.containsKey("endDate") ? params.get("endDate").toString() : "19:45:00";
            if (CalendarUtils.isEffectiveDate(nowDate, startDate, endDate)) {
                //进行提现
                if (!this.sendWithdaw(withdrawTaskPo, insertWithdrawBillMap, false)) {
                    throw GlobalException.build("提现失败");
                }
            } else {
                //如果是不在可提现范围之内
                //添加提现任务
                withdrawTaskDao.addWithdrawTask(withdrawTaskPo);
                //插入记录
                this.insertBill(withdrawTaskPo, insertWithdrawBillMap);
            }
            //endregion
        } else {
            //更新当前用户余额
            merchantWalletDao.updateCustomerBalance(customerId, -totalAmount);
            //记账
            merchantWalletDao.addAccountTrade((Map) insertWithdrawBillMap.get("addWithdrawBillMap"));
            //提现记录入库
            merchantWalletDao.addWithDraw((Map) insertWithdrawBillMap.get("customerWithDrawMap"));
        }
        Map<String, String> ress = new HashMap<>();
        ress.put("withDrawId", withDrawId);
        // 0 提现审核  1 银行转账  2 到账成功 3 到账失败
        ress.put("status", "0");
        return ress;
    }

    /**
     * 查询头寸金额
     *
     * @param clintType
     * @return
     */
    @Override
    public Long queryReserveFundBalance(String clintType) {
        String url = wcPayProperties.getAcsurl() + TlPayConstant.TRADE_QUERY_RESERVE_FUND_BALANCE;
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("clintType", clintType);
            LOGGER.info("queryReserveFundBalance--json-string---[{}]", JSONObject.toJSONString(params));
            String result = httpService.doPost(url, JSONObject.toJSONString(params), WcPayConstant.JSON);
            LOGGER.info("queryReserveFundBalance===[{}]", result);
            JSONObject object = JSONObject.parseObject(result);
            if (object.containsKey("code") && "200".equals(object.get("code").toString())) {
                return Long.parseLong(object.getString("data"));
            } else {
                LOGGER.info("queryReserveFundBalance--error--result：" + result);
                throw GlobalException.build("暂时无法提现");
            }
        } catch (Exception e) {
            LOGGER.info("queryReserveFundBalance--error：" + e.getStackTrace().toString());
            throw GlobalException.build("暂时无法提现");
        }
    }

    /* 下发提现
     *  params：withdrawTaskPo 提现任务实体类
     *  params：isTask 是否任务调用  false 不是 true 是
     * */
    @Override
    public Boolean sendWithdaw(WithdrawTaskPo withdrawTaskPo, Map<String, Object> insertWithdrawBillMap, Boolean isTask) {
        // 调用中金提现接口
        String url = wcPayProperties.getAcsurl() + TlPayConstant.TRADE_CASE_WITHDRAWAL;

        //提现前先转账
        this.withdrawTransfer(withdrawTaskPo, insertWithdrawBillMap, isTask);
        try {
            withdrawTaskPo.amount = withdrawTaskPo.receiveMoney;
            withdrawTaskPo.remark = StringUtils.isEmpty(withdrawTaskPo.remark) ? "" : withdrawTaskPo.remark;
            withdrawTaskPo.clintType = withdrawTaskPo.clientType;
            LOGGER.info("sendWithdaw--json-string---[{}]", withdrawTaskPo);
            String result = httpService.doPost(url, JSONObject.toJSONString(withdrawTaskPo), WcPayConstant.JSON);
            LOGGER.info("withdraw===[{}]", result);
            JSONObject object = JSONObject.parseObject(result);
            String status = "3";
            Boolean isSend = false;
            if (object.containsKey("code") && "200".equals(object.get("code").toString())) {
                JSONObject data = JSONObject.parseObject(object.getString("data"));
                if (("30").equals(data.getString("status"))) {
                    //成功 更新提现记录状态
                    status = "2";
                } else if (("10").equals(data.getString("status"))) {
                    // 银行处理中
                    status = "1";
                } else {
                    this.transferRefund(withdrawTaskPo);
                    if (isTask) return false;
                    throw GlobalException.build("提现失败");
                }
                //region 提现成功后做的事情
                if (!isTask) {
                    this.insertBill(withdrawTaskPo, insertWithdrawBillMap);
                }
                //修改提现的当前状态
                merchantWalletDao.updateWithDrawStatus(withdrawTaskPo.withdrawCode, status);
                //endregion
                return true;
            } else {
                //转账退款
                this.transferRefund(withdrawTaskPo);
                LOGGER.info("MerchantWalletService--sendWithdaw-error-result：" + result);
                if (isTask) return false;
                throw GlobalException.build("提现失败");
            }
        } catch (Exception e) {
            //转账退款
            this.transferRefund(withdrawTaskPo);
            LOGGER.info("MerchantWalletService--sendWithdaw-error：" + e.getStackTrace().toString());
            if (isTask) {
                //如果是任务来调用的直接返回false代表下发提现调用接口失败
                return false;
            } else {
                throw GlobalException.build("提现失败");
            }
        }
    }

    //提现转账
    private boolean withdrawTransfer(WithdrawTaskPo withdrawTaskPo, Map<String, Object> insertWithdrawBillMap, Boolean isTask) {
        try {
            //手续费给大麦
            Map<String, Object> addServiceBillMap = (Map) insertWithdrawBillMap.get("addServiceBillMap");
            Map<String, Object> transferInfoMap = new HashMap<>();
            transferInfoMap.put("withDrawId", withdrawTaskPo.withdrawCode);
            transferInfoMap.put("clientType", withdrawTaskPo.clientType);

            //调用得军接口，转账给提现手续费账户钱
            if ((isTask && withdrawTaskPo.isServiceTransfer == 0) || !isTask) {
                if (withdrawTaskPo.serviceMoney > 0) {
                    Boolean isServiceTransfer = this.transferBeforeWithdrawal(withdrawTaskPo.serviceMoney.toString(), withdrawTaskPo.clientType, (String) addServiceBillMap.get("serviceAccount"), withdrawTaskPo.serviceOrderSn);
                    if (!isServiceTransfer) {
                        if (!isTask) throw GlobalException.build("暂时无法提现");
                        else return false;
                    }
                    //region 增加提现转账记录
                    transferInfoMap.put("customerId", withdrawTaskPo.feeCustomerId);
                    transferInfoMap.put("orderSn", withdrawTaskPo.serviceOrderSn);
                    transferInfoMap.put("type", 1);
                    transferInfoMap.put("amount", withdrawTaskPo.serviceMoney);
                    merchantWalletDao.addWithdrawTransferInfo(transferInfoMap);
                    //endregion
                    if (isTask) {
                        withdrawTaskDao.updateWithDrawTransferStatus(withdrawTaskPo.withdrawId, isServiceTransfer ? 1 : 0, null);
                    }
                }
            }

            // 再次调用得军接口，转账提现金额给用户账户
            if ((isTask && withdrawTaskPo.isUserTransfer == 0) || !isTask) {
                Boolean isUserTransfer = this.transferBeforeWithdrawal(withdrawTaskPo.receiveMoney.toString(), withdrawTaskPo.clientType, withdrawTaskPo.customerId, withdrawTaskPo.customerOrderSn);
                if (!isUserTransfer) {
                    //服务费需要退款
                    merchantWalletDao.updateWithdrawTransferInfo(withdrawTaskPo.customerOrderSn);
                    //转账失败退款服务费
                    ledgerProcessService.refundTransferAmount(withdrawTaskPo.orgId, withdrawTaskPo.feeCustomerId, withdrawTaskPo.serviceOrderSn, withdrawTaskPo.clientType);
                    if (!isTask) throw GlobalException.build("暂时无法提现");
                    else return false;
                }
                //region 增加提现转账记录
                transferInfoMap.put("customerId", withdrawTaskPo.customerId);
                transferInfoMap.put("orderSn", withdrawTaskPo.customerOrderSn);
                transferInfoMap.put("type", 0);
                transferInfoMap.put("amount", withdrawTaskPo.receiveMoney);
                merchantWalletDao.addWithdrawTransferInfo(transferInfoMap);
                //endregion
                if (isTask) {
                    withdrawTaskDao.updateWithDrawTransferStatus(withdrawTaskPo.withdrawId, null, isUserTransfer ? 1 : 0);
                }
            }
            return true;
        } catch (Exception ex) {
            LOGGER.error("转账失败-------", ex);
            throw GlobalException.build("提现失败");
        }
    }

    //转账退款
    private void transferRefund(WithdrawTaskPo withdrawTaskPo) {
        //用户转账需要退款
        merchantWalletDao.updateWithdrawTransferInfo(withdrawTaskPo.customerOrderSn);
        //服务费转账需要退款
        merchantWalletDao.updateWithdrawTransferInfo(withdrawTaskPo.serviceOrderSn);
        //用户转账退款
        ledgerProcessService.refundTransferAmount(withdrawTaskPo.orgId, withdrawTaskPo.customerId, withdrawTaskPo.customerOrderSn, withdrawTaskPo.clientType);
        //服务费退款
        ledgerProcessService.refundTransferAmount(withdrawTaskPo.orgId, withdrawTaskPo.feeCustomerId, withdrawTaskPo.serviceOrderSn, withdrawTaskPo.clientType);

    }

    //记录账单等
    private void insertBill(WithdrawTaskPo withdrawTaskPo, Map<String, Object> insertWithdrawBillMap) {
        try {
            //更新当前用户余额
            merchantWalletDao.updateCustomerBalance(withdrawTaskPo.customerId, -withdrawTaskPo.withdrawMoney);
            //记账
            merchantWalletDao.addAccountTrade((Map) insertWithdrawBillMap.get("addWithdrawBillMap"));
            //提现记录入库
            merchantWalletDao.addWithDraw((Map) insertWithdrawBillMap.get("customerWithDrawMap"));

            //手续费给大麦
            Map<String, Object> addServiceBillMap = (Map) insertWithdrawBillMap.get("addServiceBillMap");

            Map<String, Object> map = new HashMap<>();
            map.put("withdrawTaskPo", withdrawTaskPo);
            map.put("addServiceBillMap", addServiceBillMap);
            //手续费进入缓存
            stringRedisTemplate.opsForValue().set("withdraw:serviceBill" + withdrawTaskPo.withdrawCode, JSON.toJSONString(map));
        } catch (Exception ex) {
            LOGGER.info("h5-withdraw-insertBill" + ex);
            throw GlobalException.build("提现失败");
        }
    }

    @Override
    public Map<String, Object> getWithDrawDetail(Map<String, Object> params) {
        Map<String, Object> result = merchantWalletDao.getWithDrawDetail(params);
        if (result == null) {
            result = merchantWalletDao.getWithDrawDetailReturn(params);
            if (result == null) {
                throw GlobalException.build("暂无该提现记录！");
            }
        }
        result.put("totalAmount", NumberUtils.fenToYuan(Long.valueOf(result.get("totalAmount").toString())));
        result.put("serviceAmount", NumberUtils.fenToYuan(Long.valueOf(result.get("serviceAmount").toString())));
        result.put("receiveAmount", NumberUtils.fenToYuan(Long.valueOf(result.get("receiveAmount").toString())));
        return result;
    }

    @Override
    public List<Map<String, Object>> detailList(String customerId) {
        List<Map<String, Object>> details = merchantWalletDao.detailList(customerId);

        details.forEach(x -> {
                    Long amount = x.get("amount") != null ? Long.parseLong(x.get("amount").toString()) : 0L;
                    x.put("amount", NumberUtils.fenToYuan(amount));
                    Long balance = Long.parseLong(x.get("balance").toString());
                    x.put("balance", NumberUtils.fenToYuan(balance));
                }
        );
        return details;
    }

    @Override
    public List<Map<String, Object>> coinList(String customerId) {
        List<Map<String, Object>> coinList = merchantWalletDao.coinListNew(customerId);
//        List<Map<String, Object>> coinList = merchantWalletDao.coinList(customerId);
        for (Map<String, Object> co : coinList) {
            Integer type = Integer.valueOf(co.get("type").toString());
            Integer amount = Integer.valueOf(co.get("amount").toString());
//            String payUser = (String) co.get("payUser");
            if (type == 0 || type == 3) {
                co.put("amount", -1 * amount);
            }
//            if (type == 3 && customerId.equals(payUser)) {
//                co.put("amount", -1 * amount);
//            }
        }
        return coinList;
    }

    @Override
    public Object capitalAccountApply(Map<String, Object> param) throws Exception {
        String result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_OPEN_PAY_ACCOUNT, JSONObject.toJSONString(param), WcPayConstant.JSON);
        JSONObject object = JSONObject.parseObject(result);
        if (object != null) {
            if (("200").equals(object.getString("code"))) {
                JSONObject data = JSONObject.parseObject(object.getString("data"));
                if (("30").equals(data.getString("status"))) {
                    //中金返回成功
                    //判断联汇资金账户是否存在进行新增更新操作
//                if(platformSetNameDao.ifCapitalAccountExist(param)>0){
//                    platformSetNameDao.capitalAccountUpdate(param);
//                }else{
//                    platformSetNameDao.capitalAccountApply(param);
//                }
                }
                return data;
            } else {
                throw GlobalException.build("开通失败：" + object.get("msg").toString());
            }
        } else {
            throw GlobalException.build("开通失败");
        }

    }

    @Override
    public Boolean sendVerificationCode(Map param) throws IOException, URISyntaxException {
        String result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_SEND_VERIFICATION_CODE, JSONObject.toJSONString(param), WcPayConstant.JSON);
        JSONObject object = JSONObject.parseObject(result);
        if (object != null) {
            if (("200").equals(object.getString("code"))) {
                return true;
            }
        }
        return false;
    }

    @Override
    public Map tosigncontract(Map<String, String> param) throws IOException, URISyntaxException {
        String result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_BIND_PHONE, JSONObject.toJSONString(param), WcPayConstant.JSON);
        JSONObject object = JSONObject.parseObject(result);
        if (object != null) {
            if ("200".equals(object.getString("code"))) {
                return (Map) object.get("data");
            } else {
                throw GlobalException.build(object.getString("msg"));
            }
        }
        throw GlobalException.build("系统繁忙，请稍后再试(err=yzsj)");
    }

    @Override
    public Map changePhone(Map<String, String> param) throws IOException, URISyntaxException {
        String result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.CHANGE_PHONE, JSONObject.toJSONString(param), WcPayConstant.JSON);
        JSONObject object = JSONObject.parseObject(result);
        if (object != null) {
            if ("200".equals(object.getString("code"))) {
                return (Map) object.get("data");
            } else {
                GlobalException.build(object.getString("msg"));
            }
        }
        throw GlobalException.build("系统繁忙，请稍后再试(err=ghsj)");
    }

    /**
     * flag 是否需要验证手机号
     *
     * @param map
     * @return
     */
    @Override
    public Map<String, Object> accountStatus(Map<String, Object> map) {
        LOGGER.info("accountStatus===" + JSON.toJSONString(map));
        Map<String, Object> accountStatus = merchantWalletDao.getAccountStatusByCustomerId(map);
        Map<String, Object> result = new HashMap<>();
        if (accountStatus == null) {
            // 未开户
            result.put("status", 4);
            return result;
        }

        boolean realnameflag = true;
        if (map.containsKey("realnameflag")) {
            realnameflag = (boolean) map.get("realnameflag");
        }
        if (realnameflag) {
            Integer realnameStatus = (Integer) accountStatus.get("realnameStatus");
            if (realnameStatus == null || realnameStatus == 0) {
                // 未实名认证
                result.put("status", 0);
                return result;
            }
        }

        boolean flag = true;
        if (map.containsKey("flag")) {
            flag = (boolean) map.get("flag");
        }

        if (flag) {
            Integer bindphoneStatus = (Integer) accountStatus.get("bindphoneStatus");
            if (bindphoneStatus == null || bindphoneStatus == 0) {
                // 已开户，未验证手机号 2020-03-16 去掉
                result.put("status", 1);
                String phoneNumber = (String) accountStatus.get("customerPhone");
                result.put("phone", phoneNumber);
                return result;
            }
        }

        Integer signStatus = (Integer) accountStatus.get("signStatus");
        if (signStatus == 0) {
            // 已开户，验证手机号，但未通过协议认证
            result.put("status", 2);
            // 协议地址
            String url = wcPayProperties.getAcsurl() + TlPayConstant.USER_TO_SIGN_CONTRACT;
            String res;
            try {
                String orgId = (String) map.get("orgId");
                String clintType = maiBaoLaService.getAlias(orgId);
                map.put("clintType", clintType);
                res = httpService.doPost(url, JSONObject.toJSONString(map), WcPayConstant.JSON);
            } catch (URISyntaxException | IOException e) {
                LOGGER.error("调用通联接口异常", e);
                throw GlobalException.build("调用通联接口异常");
            }
            LOGGER.info("USER_TO_SIGN_CONTRACT===res===[{}]", res);
            Map parse = (Map) JSONObject.parse(res);
            if ("200".equals(parse.get("code"))) {
                Map data = (Map) parse.get("data");
                String contractUrl = (String) data.get("contractUrl");
                result.put("redirectUrl", contractUrl);
                return result;
            } else {
                throw GlobalException.build("获取签名地址失败");
            }
        }
        result.put("status", 3);
        return result;
    }

    @Override
    public Map setRealName(Map<String, String> params) {
        String clintType = maiBaoLaService.getAlias(params.get("orgId"));
        params.put("clintType", clintType);
        try {
            String result = httpService.doPost(wcPayProperties.getAcsurl() + TlPayConstant.USER_SET_REAL_NAME, JSONObject.toJSONString(params), WcPayConstant.JSON);
            LOGGER.info("setRealName:" + result);
            if (StringUtils.isEmpty(result)) {
                throw GlobalException.build("调用通联接口异常!");
            }
            Map res = (Map) JSON.parse(result);
            if (!res.containsKey("code") || !res.containsKey("msg")) {
                throw GlobalException.build("调用通联接口异常.");
            }
            if (!"200".equals(res.get("code"))) {
                throw GlobalException.build(res.get("msg").toString());
            }
            return (Map) JSON.parse(res.get("data").toString());
        } catch (Exception e) {
            LOGGER.error("调用通联接口异常", e);
            throw GlobalException.build("调用通联接口异常");
        }
    }

    @Override
    public Map<String, Object> getRefundDetail(Map<String, Object> params) {
        return maiBaoLaService.getRefundDetail(params);
    }

    @Override
    public List<Map<String, Object>> getSettlementDetail(String customerId) {
        List<Map<String, Object>> settlementDetail = merchantWalletDao.getMoneySettlementDetail(customerId, 1);
        for (Map<String, Object> da : settlementDetail) {
            List<Map<String, Object>> temp = new ArrayList<>();
            String[] types = da.get("type").toString().split(",");
            String[] groupAmount = da.get("groupAmount").toString().split(",");

            if ("-1".equals(da.get("goodsId").toString()) && "-1".equals(da.get("orderId").toString())) {
                for (int i = 0; i < types.length; i++) {
                    da.put("type", types[i]);
                    da.put("goodsNum", 1);
                    Map<String, Object> feeDetail = new HashMap<>();
                    Integer amount = Integer.valueOf(groupAmount[i]);
                    feeDetail.put("amount", NumberUtils.fenToYuan(Long.valueOf(amount)));
                    feeDetail.put("type", Integer.parseInt(types[i]));
                    feeDetail.put("goodsNum", 1);
                    temp.add(feeDetail);
                }
                if ("0".equals(da.get("isEnd").toString())) {
                    da.put("status", 1);
                } else {
                    da.put("status", 4);
                }
            } else {
                da.put("types", types);
                da.put("flag", 1);
                temp = merchantWalletDao.getFeeDetailList(da);
                String isEnd = da.get("isEnd").toString();
                String refundStatus = da.get("refundStatus").toString();
                Integer status = this.getStatus(isEnd, refundStatus);
                da.put("status", status);
            }
            da.put("allAmount", NumberUtils.fenToYuan(Long.valueOf(da.get("allAmount").toString())));
            da.put("feeDetail", temp);
        }
        return settlementDetail;
    }

    private Integer getStatus(String isEnd, String refundStatus) {
        Integer status;
        if ("6".equals(refundStatus) || "5".equals(refundStatus)) {
            status = 3;//已退款
        } else if (!"0".equals(refundStatus)) {
            status = 2;//退款中
        } else if ("0".equals(isEnd)) {
            status = 1;//结算中
        } else {
            status = 4;//已结算
        }
//        if ("0".equals(isEnd)) {//维权期中
//            if ("0".equals(refundStatus) || "6".equals(refundStatus) || "7".equals(refundStatus)) {//没有处于退款中
//                status = 1;//结算中
//            } else {//处于退款中
//                status = 2;//退款中
//            }
//        } else {//不在维权期
//            if ("6".equals(refundStatus)) {//退款完成
//                status = 3;//已退款
//            } else {
//                status = 4;//已结算
//            }
//        }
        return status;
    }

    @Override
    public List<Map<String, Object>> getScoreSettlementDetail(String customerId) {
        List<Map<String, Object>> settlementDetail = merchantWalletDao.getMoneySettlementDetail(customerId, 2);
        for (Map<String, Object> da : settlementDetail) {
            List<Map<String, Object>> temp = new ArrayList<>();
            String[] types = da.get("type").toString().split(",");
            String[] groupAmount = da.get("groupAmount").toString().split(",");

            if ("-1".equals(da.get("goodsId").toString()) && "-1".equals(da.get("orderId").toString())) {
                for (int i = 0; i < types.length; i++) {
                    da.put("type", types[i]);
                    da.put("goodsNum", 1);
                    Map<String, Object> feeDetail = new HashMap<>();
                    Integer amount = Integer.valueOf(groupAmount[i]);
                    feeDetail.put("amount", NumberUtils.fenToYuan(Long.valueOf(amount)));
                    feeDetail.put("type", Integer.parseInt(types[i]));
                    feeDetail.put("goodsNum", 1);
                    temp.add(feeDetail);
                }
                if ("0".equals(da.get("isEnd").toString())) {
                    da.put("status", 1);
                } else {
                    da.put("status", 4);
                }
            } else {
                da.put("types", types);
                da.put("flag", 2);
                temp = merchantWalletDao.getFeeDetailList(da);
                String isEnd = da.get("isEnd").toString();
                String refundStatus = da.get("refundStatus").toString();
                Integer status = this.getStatus(isEnd, refundStatus);
                da.put("status", status);
            }
            da.put("allAmount", Long.valueOf(da.get("allAmount").toString()));
            da.put("feeDetail", temp);
        }
        return settlementDetail;
//        List<Map<String, Object>> settlementDetail = merchantWalletDao.getSettlementDetail(customerId, 2);
//        for (Map<String, Object> map : settlementDetail) {
//            String isEnd = map.get("isEnd").toString();
//            String refundStatus = map.get("refundStatus").toString();
//            Integer status = this.getStatus(isEnd, refundStatus);
//            map.put("status", status);
//        }
//        return settlementDetail;
    }

    /**
     * 提现前的转账
     *
     * @param amount     转账金额
     * @param clintType  平台别名
     * @param customerId 用户ID
     * @param orderSn    平台订单ID
     */
    @Override
    public Boolean transferBeforeWithdrawal(String amount, String clintType, String customerId, String orderSn) {
        if ("#yunBizUserId_B2C#".equals(customerId)) {
            return false;
        }
        String url = wcPayProperties.getAcsurl() + TlPayConstant.TRADE_APPLICATION_TRANSFER;
        Map<String, Object> map = new HashMap<>();
        // 转账金额
        map.put("amount", amount);
        // 平台别名，测试使用yt
        map.put("clintType", clintType);
        // 用户ID
        map.put("customerId", customerId);
        // 平台订单ID
        map.put("orderSn", orderSn);
        String result;
        LOGGER.info("transferBeforeWithdrawal===request[{}]", JSON.toJSONString(map));
        try {
            result = httpService.doPost(url, JSON.toJSONString(map), WcPayConstant.JSON);
            LOGGER.info("transferBeforeWithdrawal===result[{}]", result);
            if (result == null) {
                return false;
            }
            Map parse = (Map) JSON.parse(result);
            if (parse.containsKey("code") && !parse.get("code").toString().equals("200")) {
                LOGGER.info("transferBeforeWithdrawal===提现失败：", result);
                return false;
            } else {
                if (parse.containsKey("data") && !StringUtils.isEmpty(parse.get("data"))) {
                    JSONObject data = JSONObject.parseObject(parse.get("data").toString());
                    if (("30").equals(data.getString("status"))) {
                        return true;
                    } else {
                        LOGGER.info("transferBeforeWithdrawal===提现失败：", result);
                        return false;
                    }
                } else {
                    return false;
                }
            }
        } catch (URISyntaxException | IOException e) {
            LOGGER.error("transferBeforeWithdrawal---转账失败，通联网关调用异常", e);
            return false;
        }
    }
}
